package cn.ac.aircas.common.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
/**
 * @author 桔梗迷
 * @date 2023/10/19 14:35
 */
public class AesUtils {

    private static final Log log = LogFactory.getLog(AesUtils.class);

    private static final java.util.Base64.Encoder ENCODER = java.util.Base64.getEncoder();
    private static final java.util.Base64.Decoder DECODER = java.util.Base64.getDecoder();

    /**
     * 默认key 16位byte[] [106, -26, -43, -79, -22, 11, -49, 112, 100, -111, -27, -54, 9, 115, 115, 50]
     */
    private static final String DEFAULT_KEY = "aubVseoLz3BkkeXKCXNzMg==";
    /**
     * 默认向量 16位byte[] {25, 101, -116, -100, 98, 100, -125, 126, -57, -26, 3, 107, -45, 79, -34, -19}
     */
    public static final String DEFAULT_IV = "GWWMnGJkg37H5gNr00/e7Q==";

    /**
     * 对称加密
     *
     * @param plainText 明文
     */
    public static String encrypt(String plainText) throws Exception {
        return encrypt(plainText, DEFAULT_KEY);
    }

    /**
     * 对称加密
     *
     * @param key       密钥
     * @param plainText 明文
     */
    public static String encrypt(String plainText, String key) throws Exception {
        return encrypt(plainText, key, DEFAULT_IV);
    }

    /**
     * 对称加密
     *
     * @param secretKey 密钥
     * @param iv        加密向量，只有CBC模式才支持
     * @param plainText 明文
     */
    public static String encrypt(String plainText, String secretKey, String iv) throws Exception {
        if (StringUtils.isAnyEmpty(plainText, secretKey, iv)) {
            log.error("存在空值！！");
            return null;
        }
        SecretKey key = new SecretKeySpec(DECODER.decode(secretKey), "AES");
        byte[] plainTextInBytes = plainText.getBytes(StandardCharsets.UTF_8);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(DECODER.decode(iv)));
        return ENCODER.encodeToString(cipher.doFinal(plainTextInBytes));
    }

    /**
     * 对称解密
     *
     * @param cipherText 密文
     */
    public static String decrypt(String cipherText) throws Exception {
        return decrypt(cipherText, DEFAULT_KEY);
    }

    /**
     * 对称解密
     *
     * @param key        密钥
     * @param cipherText 密文
     */
    public static String decrypt(String cipherText, String key) throws Exception {
        return decrypt(cipherText, key, DEFAULT_IV);
    }

    /**
     * 对称解密
     *
     * @param secretKey  密钥
     * @param iv         加密向量(需要16位byte数组字符串)，只有CBC模式才支持
     * @param ciphertext 密文
     */
    public static String decrypt(String ciphertext, String secretKey, String iv) throws Exception {
        if (StringUtils.isAnyEmpty(ciphertext, secretKey, iv)) {
            log.error("存在空值！！");
            return null;
        }
        SecretKey key = new SecretKeySpec(DECODER.decode(secretKey), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(DECODER.decode(iv));
        byte[] ciphertextInBytes = DECODER.decode(ciphertext);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
        return new String(cipher.doFinal(ciphertextInBytes), StandardCharsets.UTF_8);
    }


    public static void main(String[] args) throws Exception {
        String str = "hello word!";
        String pwd = encrypt(str);
        System.out.println("密文字符串1：" + pwd);
        System.out.println(decrypt(pwd));
        System.out.println("----------------------------");
        byte[] bytes = new SecureRandom().generateSeed(16);
        String key = ENCODER.encodeToString(bytes);
        System.out.println("key2：");
        pwd = encrypt(str, key);
        System.out.println("密文字符串2：" + pwd);
        System.out.println(decrypt(pwd, key));
        System.out.println("----------------------------");
        byte[] keyArr = new SecureRandom().generateSeed(16);
        byte[] ivArr = new SecureRandom().generateSeed(16);
        key = ENCODER.encodeToString(keyArr);
        String iv = ENCODER.encodeToString(ivArr);
        pwd = encrypt(str, key, iv);
        System.out.println("key3：" + key);
        System.out.println("iv3：" + iv);
        System.out.println("密文字符串3：" + pwd);
        System.out.println(decrypt(pwd, key, iv));
    }
}

